package cn.com.thinker.security.server.config;

import cn.com.thinker.security.sdk.sso.authentication.EncryCredentialManager;
import cn.com.thinker.security.sdk.sso.authentication.EncryCredentialManagerImpl;
import cn.com.thinker.security.sdk.sso.filter.Thin4soLogoutJavascriptFilter;
import cn.com.thinker.security.sdk.sso.key.KeyService;
import cn.com.thinker.security.server.core.app.AppService;
import cn.com.thinker.security.server.core.app.AppServiceImpl;
import cn.com.thinker.security.server.core.authentication.AuthenticationManager;
import cn.com.thinker.security.server.core.authentication.AuthenticationManagerImpl;
import cn.com.thinker.security.server.core.authentication.AuthenticationPostHandler;
import cn.com.thinker.security.server.core.authentication.handlers.AuthenticationHandler;
import cn.com.thinker.security.server.core.authentication.handlers.SimpleTestUsernamePasswordAuthenticationHandler;
import cn.com.thinker.security.server.core.authentication.resolvers.CredentialToPrincipalResolver;
import cn.com.thinker.security.server.core.authentication.status.DefaultUserLoggedStatusStore;
import cn.com.thinker.security.server.core.authentication.status.UserLoggedStatusStore;
import cn.com.thinker.security.server.core.key.KeyServiceImpl;
import cn.com.thinker.security.server.resolver.CompositeCredentialResolver;
import cn.com.thinker.security.server.resolver.CredentialResolver;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;

/**
 * Created by crazyHC on 2017/6/29.
 */
@Configuration
public class SecurityServerConfig {

    @Resource
    private CredentialResolver encryCredentialResolver;
    @Resource
    private CredentialResolver usernamePasswordCredentialResolver;
    @Resource
    private AuthenticationHandler usernamePasswordAuthenticationHandler;
    @Resource
    private AuthenticationHandler encryCredentialAuthenticationHandler;
    @Resource
    private CredentialToPrincipalResolver usernamePasswordCredentialToPrincipalResolver;
    @Resource
    private CredentialToPrincipalResolver encryCredentialToPrincipalResolver;
    @Resource
    private AuthenticationPostHandler defaultAuthenticationPostHandler;

    @Value("${thinker.security.server.keys.path}")
    private String keys;

    @Value("${thinker.security.server.apps.path}")
    private String apps;


    @Bean(autowire = Autowire.BY_NAME)
    public EncryCredentialManager encryCredentialManager() {
        return new EncryCredentialManagerImpl();
    }

    @Bean(autowire = Autowire.BY_NAME)
    public AuthenticationHandler usernamePasswordAuthenticationHandler() {
        return new SimpleTestUsernamePasswordAuthenticationHandler();
    }


    @Bean(autowire = Autowire.BY_NAME)
    public FilterRegistrationBean logoutJavascriptFilter() {
        FilterRegistrationBean filter = new FilterRegistrationBean();
        filter.setFilter(new Thin4soLogoutJavascriptFilter());
        Map<String, String> params = Maps.newHashMap();
        // 当前应用的登出地址
        params.put("currentAppLogoutUrl", "/logout");
        // 登出后跳转地址
        params.put("logoutSuccessUrl", "/login");
        // sso服务器主机地址
        params.put("thin4soServerHost", "/");
        filter.setInitParameters(params);
        filter.setUrlPatterns(Lists.newArrayList("/logout.js"));
        return filter;
    }

    /**
     * 组合凭据解析器对象。
     *
     * @return
     */
    @Bean(autowire = Autowire.BY_NAME)
    public CompositeCredentialResolver credentialResolver() {
        CompositeCredentialResolver compositeCredentialResolver = new CompositeCredentialResolver();
        compositeCredentialResolver.setEncryCredentialResolver(encryCredentialResolver);
        compositeCredentialResolver.setUsernamePasswordCredentialResolver(usernamePasswordCredentialResolver);
        return compositeCredentialResolver;
    }

    @Bean(autowire = Autowire.BY_NAME)
    public AppService appService() {
        AppServiceImpl appService = new AppServiceImpl();
        if(StringUtils.isNotBlank(apps))
            appService.setExternalData(apps);
        return appService;
    }

    @Bean(autowire = Autowire.BY_NAME)
    public KeyService keyService() {
        KeyServiceImpl keyService = new KeyServiceImpl();
        if(StringUtils.isNotBlank(keys))
            keyService.setExternalData(keys);
        return keyService;
    }

    /**
     * 默认的用户登录状态存储器服务。
     *
     * @return
     */
    @Bean(autowire = Autowire.BY_NAME)
    public UserLoggedStatusStore userLoggedStatusStore() {
        return new DefaultUserLoggedStatusStore();
    }

    @Bean(autowire = Autowire.BY_NAME)
    public AuthenticationManager authenticationManager() {
        AuthenticationManagerImpl authenticationManager = new AuthenticationManagerImpl();
        authenticationManager.setAuthenticationHandlers(Lists.newArrayList(usernamePasswordAuthenticationHandler, encryCredentialAuthenticationHandler));
        authenticationManager.setCredentialToPrincipalResolvers(Lists.newArrayList(usernamePasswordCredentialToPrincipalResolver, encryCredentialToPrincipalResolver));
        authenticationManager.setAuthenticationPostHandler(defaultAuthenticationPostHandler);
        return authenticationManager;
    }


}
